package org.railage.client.gui.tabs;

import java.io.IOException;
import java.text.ParseException;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;

import org.apache.log4j.Logger;
import org.railage.client.Client;
import org.railage.client.gui.main.GUI;
import org.railage.common.dto.StationOfRouteDTO;

import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.MaskFormatter;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.JSeparator;

public class EditRoutesTab extends AbstractTab {

	private static final long serialVersionUID = -3404641839514507539L;

	private static final Logger log = Logger.getLogger(EditRoutesTab.class);

	private static final String SELECT_ROUTE = "-- Select route --";
	private static final String SELECT_STATION = "-- Select station --";
	private static final String DELETE_CONFIRM_TITLE = "Route delete confirmation";

	private String[] routes = null;
	private String[] stations = null;
	private String[] existingStationsColumnNames = new String[] { "#",
			"Station name", "Time after start", "Time on station" };
	private String[] newStationsColumnNames = new String[] { "#",
			"Station name", "Time after prev", "Time on station" };

	private JFormattedTextField timeAfterPrevField;
	private JFormattedTextField timeOnStationField;
	private JComboBox<String> stationBox;
	private JComboBox<String> routesBox;
	private JTable newStationsTable;
	private JTable existingStationsTable;
	private JTextField newRouteNameField;

	public EditRoutesTab() {
		setLayout(null);

		JLabel lblNewRouteName = new JLabel("New route name");
		lblNewRouteName.setBounds(10, 11, 101, 14);
		add(lblNewRouteName);

		newRouteNameField = new JTextField();
		newRouteNameField.setBounds(163, 8, 151, 20);
		add(newRouteNameField);
		newRouteNameField.setColumns(10);

		JLabel lblStation = new JLabel("Station");
		lblStation.setBounds(10, 65, 143, 14);
		add(lblStation);

		stationBox = new JComboBox<String>();
		stationBox.setBounds(163, 62, 151, 20);
		add(stationBox);

		JLabel lblTimeAfterPrev = new JLabel("Time after previous");
		lblTimeAfterPrev.setBounds(10, 99, 143, 14);
		add(lblTimeAfterPrev);

		timeAfterPrevField = new JFormattedTextField(
				createFormatter("##:##:##"));
		timeAfterPrevField.setBounds(163, 96, 151, 20);
		add(timeAfterPrevField);

		JLabel lblTimeOnStation = new JLabel("Time on station");
		lblTimeOnStation.setBounds(10, 130, 143, 14);
		add(lblTimeOnStation);

		timeOnStationField = new JFormattedTextField(
				createFormatter("##:##:##"));
		timeOnStationField.setBounds(163, 127, 151, 20);
		add(timeOnStationField);

		JButton btnAdd = new JButton("Add");
		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				addStation();
			}
		});
		btnAdd.setBounds(225, 158, 89, 23);
		add(btnAdd);

		JButton btnSave = new JButton("Save");
		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveRoute();
			}
		});
		btnSave.setBounds(10, 158, 89, 23);
		add(btnSave);

		JScrollPane scrollPaneNewStations = new JScrollPane();
		scrollPaneNewStations.setBounds(345, 0, 375, 195);
		add(scrollPaneNewStations);

		newStationsTable = new JTable();
		scrollPaneNewStations.setViewportView(newStationsTable);

		JScrollPane scrollPaneExistingStations = new JScrollPane();
		scrollPaneExistingStations.setBounds(345, 195, 375, 195);
		add(scrollPaneExistingStations);

		existingStationsTable = new JTable();
		scrollPaneExistingStations.setViewportView(existingStationsTable);

		JLabel lblExistingRoutes = new JLabel("Existing routes");
		lblExistingRoutes.setBounds(10, 211, 101, 14);
		add(lblExistingRoutes);

		JLabel lblRouteName = new JLabel("Route name");
		lblRouteName.setBounds(10, 256, 143, 14);
		add(lblRouteName);

		routesBox = new JComboBox<String>();
		routesBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				fillExistingStationsTable((String) routesBox.getSelectedItem());
			}
		});
		routesBox.setBounds(163, 253, 151, 20);
		add(routesBox);

		JButton btnDelete = new JButton("Delete");
		btnDelete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				deleteRoute((String) routesBox.getSelectedItem());
			}
		});
		btnDelete.setBounds(225, 284, 89, 23);
		add(btnDelete);

		JSeparator separator = new JSeparator();
		separator.setBounds(10, 194, 326, 2);
		add(separator);
	}

	public void init() {
		fillStationsComboBox();
		fillRoutesComboBox();
		fillExistingStationsTable(SELECT_ROUTE);
		fillNewStationsTable(new Object[][] {});
		
		timeAfterPrevField.setText("00:00:00");
		timeAfterPrevField.setEditable(false);
		timeOnStationField.setText("00:00:00");
		timeOnStationField.setEditable(false);
		
	}

	private void fillNewStationsTable(Object[][] data) {
		newStationsTable.setModel(new DefaultTableModel(data,
				newStationsColumnNames) {
			private static final long serialVersionUID = -2784740590525261101L;

			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});
		newStationsTable.getColumnModel().getColumn(0).setPreferredWidth(30);
		newStationsTable.getColumnModel().getColumn(1).setPreferredWidth(200);
		newStationsTable.getColumnModel().getColumn(2).setPreferredWidth(150);
		newStationsTable.getColumnModel().getColumn(3).setPreferredWidth(150);
	}

	private void addStation() {
		if (!((String) stationBox.getSelectedItem()).equals(SELECT_STATION)) {
			DefaultTableModel model = (DefaultTableModel) newStationsTable
					.getModel();
			model.addRow(new Object[] { newStationsTable.getRowCount() + 1,
					(String) stationBox.getSelectedItem(),
					timeAfterPrevField.getText(), timeOnStationField.getText() });
			stationBox.removeItemAt(stationBox.getSelectedIndex());
			stationBox.setSelectedIndex(0);
			timeAfterPrevField.setEditable(true);
			timeOnStationField.setEditable(true);
		} else {
			JOptionPane.showMessageDialog(this, "Please select station");
		}
	}

	private void saveRoute() {
		int rowCount = newStationsTable.getRowCount();

		if (rowCount > 1 && !newRouteNameField.getText().equals("")) {
			String[] newStations = new String[rowCount];
			String[] timesAfterPrev = new String[rowCount];
			String[] timesOnStation = new String[rowCount];
			for (int i = 0; i < rowCount; i++) {
				newStations[i] = (String) newStationsTable.getValueAt(i, 1);
				timesAfterPrev[i] = (String) newStationsTable.getValueAt(i, 2);
				timesOnStation[i] = (String) newStationsTable.getValueAt(i, 3);
			}

			Object[] request = new Object[] { newRouteNameField.getText(),
					newStations, timesAfterPrev, timesOnStation

			};

			String result = null;
			try {
				result = (String) Client.getInstance().callMethod("addRoute",
						request);
				JOptionPane.showMessageDialog(this, result);
				if (result.equals("Route added")) {
					fillNewStationsTable(new Object[][] {});
					
					timeAfterPrevField.setText("00:00:00");
					timeAfterPrevField.setEditable(false);
					timeOnStationField.setText("00:00:00");
					timeOnStationField.setEditable(false);
				}
			} catch (IOException e) {
				log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
				JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
			}

			fillRoutesComboBox();

		} else if (newRouteNameField.getText().equals("")) {
			JOptionPane.showMessageDialog(this,
					"Please insert new route's name");
		} else if (rowCount <= 1) {
			JOptionPane.showMessageDialog(this, "Please add more stations");
		}
	}

	private void deleteRoute(String routeName) {
		if (!routeName.equals(SELECT_ROUTE)) {
			int confirmed = JOptionPane.showConfirmDialog(this,
					"Are you sure you want to delete route " + routeName + "?",
					DELETE_CONFIRM_TITLE, JOptionPane.YES_NO_OPTION);
			if (confirmed == 0) {
				String result = null;
				try {
					result = (String) Client.getInstance().callMethod(
							"deleteRoute", routeName);
					if (result.equals("Route deleted")) {
						fillRoutesComboBox();
						fillExistingStationsTable(SELECT_ROUTE);
					}
					JOptionPane.showMessageDialog(this, result);
				} catch (IOException e) {
					log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
					JOptionPane.showMessageDialog(this,
							GUI.DISCON_UNEXP_GUI_MSG);
				}
			}
		} else {
			JOptionPane.showMessageDialog(this, "Please select route");
		}
	}

	private void fillRoutesComboBox() {
		try {
			routes = (String[]) Client.getInstance().callMethod(
					"getRouteNames", null);
			String[] items = new String[routes.length + 1];
			items[0] = SELECT_ROUTE;
			System.arraycopy(routes, 0, items, 1, routes.length);

			routesBox.setModel(new DefaultComboBoxModel<String>(items));
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
	}

	private void fillExistingStationsTable(String routeName) {
		Object[][] data = new Object[][] {};
		if (!routeName.equals(SELECT_ROUTE)) {
			StationOfRouteDTO[] stationsOfRoute = null;
			try {
				stationsOfRoute = (StationOfRouteDTO[]) Client.getInstance()
						.callMethod("getOrderedStationsOfRoute", routeName);
				data = new Object[stationsOfRoute.length][];

				int i = 0;
				for (StationOfRouteDTO stationOfRoute : stationsOfRoute) {
					data[i] = new Object[] { stationOfRoute.getStationOrder(),
							stationOfRoute.getStationName(),
							stationOfRoute.getTimeAfterStart(),
							stationOfRoute.getTimeOnStation() };
					i++;
				}
			} catch (IOException e) {
				log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
				JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
			}
		}
		existingStationsTable.setModel(new DefaultTableModel(data,
				existingStationsColumnNames) {
			private static final long serialVersionUID = 7203675172826916068L;

			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});
		existingStationsTable.getColumnModel().getColumn(0)
				.setPreferredWidth(30);
		existingStationsTable.getColumnModel().getColumn(1)
				.setPreferredWidth(200);
		existingStationsTable.getColumnModel().getColumn(2)
				.setPreferredWidth(150);
		existingStationsTable.getColumnModel().getColumn(3)
				.setPreferredWidth(150);
	}

	private void fillStationsComboBox() {
		try {
			stations = (String[]) Client.getInstance().callMethod(
					"getStationNames", null);
			String[] items = new String[stations.length + 1];
			items[0] = SELECT_STATION;
			System.arraycopy(stations, 0, items, 1, stations.length);

			stationBox.setModel(new DefaultComboBoxModel<String>(items));
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
	}

	private MaskFormatter createFormatter(String s) {
		MaskFormatter formatter = null;
		try {
			formatter = new MaskFormatter(s);
		} catch (ParseException e) {
			log.error("formatter is bad: " + e.getMessage());
		}
		return formatter;
	}
}
